home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS01.ADF / C / aterm.c < prev    next >
C/C++ Source or Header  |  1986-01-14  |  34KB  |  1,119 lines

  1. /************************************************************************
  2. *  a terminal program that has ascii and xmodem transfer capability
  3. *
  4. *  use esc to abort xmodem transfer
  5. *
  6. *  written by Michael Mounier
  7. *
  8. *  Modification History -
  9. *   December 85 - added 80 * 25 capabilities  - Larry Phillips
  10. *   Jan 9 1985  - added XMODEM pad stripping on download  - Larry Phillips
  11. *                 added comments to startup screen - Larry Phillips.
  12. ************************************************************************/
  13.  
  14. /*  compiler directives to fetch the necessary header files */
  15. #include <exec/types.h>
  16. #include <exec/exec.h>
  17. #include <intuition/intuition.h>
  18. #include <intuition/intuitionbase.h>
  19. #include <graphics/gfxbase.h>
  20. #include <graphics/gfx.h>
  21. #include <graphics/text.h>
  22. #include <graphics/regions.h>
  23. #include <graphics/copper.h>
  24. #include <graphics/gels.h>
  25. #include <devices/serial.h>
  26. #include <devices/keymap.h>
  27. #include <hardware/blit.h>
  28. #include <stdio.h>
  29. #include <ctype.h>
  30. #include <libraries/dos.h>
  31.  
  32. #define INTUITION_REV 1
  33. #define GRAPHICS_REV  1
  34.  
  35. /* things for xmodem send and recieve */
  36. #define SECSIZ   0x80
  37. #define TTIME    30          /* number of seconds for timeout */
  38. #define BufSize  0x1000     /* Text buffer */
  39. #define ERRORMAX 10        /* Max errors before abort */
  40. #define RETRYMAX 10       /* Maximum retrys before abort */
  41. #define SOH      1       /* Start of sector char */
  42. #define EOT      4      /* end of transmission char */
  43. #define ACK      6     /* acknowledge sector transmission */
  44. #define NAK      21   /* error in transmission detected */
  45.  
  46. static char
  47.     bufr[BufSize];
  48. static int
  49.     fd,
  50.     timeout = FALSE;
  51. static long
  52.     bytes_xferred;
  53.  
  54. /*   Intuition always wants to see these declarations */
  55. struct IntuitionBase *IntuitionBase;
  56. struct GfxBase *GfxBase;
  57.  
  58. /* my window structure */
  59. struct NewWindow NewWindow = {
  60.    0,
  61.    0,
  62.    640,
  63.    200,
  64.    0,
  65.    1,
  66.    CLOSEWINDOW | RAWKEY | MENUPICK | NEWSIZE,
  67.    WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDEPTH | REPORTMOUSE
  68.    | BORDERLESS,
  69.    NULL,
  70.    NULL,
  71.    "AMIGA Terminal",
  72.    NULL,
  73.    NULL,
  74.    100, 35,
  75.    640, 200,
  76.    WBENCHSCREEN,
  77. };
  78.  
  79. struct Window *mywindow;             /* ptr to applications window */
  80. struct IntuiMessage *NewMessage;    /* msg structure for GetMsg() */
  81.  
  82. /*****************************************************
  83. *                     File Menu
  84. *****************************************************/
  85.  
  86. /* define maximum number of menu items */
  87. #define FILEMAX 4
  88.  
  89. /*   declare storage space for menu items and
  90.  *   their associated IntuiText structures
  91.  */
  92. struct MenuItem FileItem[FILEMAX];
  93. struct IntuiText FileText[FILEMAX];
  94.  
  95. /*****************************************************************/
  96. /*    The following function initializes the structure arrays    */
  97. /*   needed to provide the File menu topic.                      */
  98. /*****************************************************************/
  99. InitFileItems()
  100. {
  101. short n;
  102.  
  103. /* initialize each menu item and IntuiText with loop */
  104. for( n=0; n<FILEMAX; n++ )
  105.    {
  106.    FileItem[n].NextItem = &FileItem[n+1];
  107.    FileItem[n].LeftEdge = 0;
  108.    FileItem[n].TopEdge = 11 * n;
  109.    FileItem[n].Width = 135;
  110.    FileItem[n].Height = 11;
  111.    FileItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX;
  112.    FileItem[n].MutualExclude = 0;
  113.    FileItem[n].ItemFill = (APTR)&FileText[n];
  114.    FileItem[n].SelectFill = NULL;
  115.    FileItem[n].Command = 0;
  116.    FileItem[n].SubItem = NULL;
  117.    FileItem[n].NextSelect = 0;
  118.  
  119.    FileText[n].FrontPen = 0;
  120.    FileText[n].BackPen = 1;
  121.    FileText[n].DrawMode = JAM2;     /* render in fore and background */
  122.    FileText[n].LeftEdge = 0;
  123.    FileText[n].TopEdge = 1;
  124.    FileText[n].ITextFont = NULL;
  125.    FileText[n].NextText = NULL;
  126.    }
  127. FileItem[FILEMAX-1].NextItem = NULL;
  128.  
  129. /* initialize text for specific menu items */
  130. FileText[0].IText = (UBYTE *)"Ascii Capture";
  131. FileText[1].IText = (UBYTE *)"Ascii Send";
  132. FileText[2].IText = (UBYTE *)"Xmodem Receive";
  133. FileText[3].IText = (UBYTE *)"Xmodem Send";
  134.  
  135. return( 0 );
  136. }
  137.  
  138. /*****************************************************/
  139. /*                BaudRate  Menu                     */
  140. /*****************************************************/
  141.  
  142. /* define maximum number of menu items */
  143. #define RSMAX 5
  144.  
  145. /*   declare storage space for menu items and
  146.  *   their associated IntuiText structures
  147.  */
  148. struct MenuItem RSItem[RSMAX];
  149. struct IntuiText RSText[RSMAX];
  150.  
  151. /*****************************************************************/
  152. /*    The following function initializes the structure arrays    */
  153. /*   needed to provide the BaudRate menu topic.                  */
  154. /*****************************************************************/
  155. InitRSItems()
  156. {
  157. short n;
  158.  
  159. /* initialize each menu item and IntuiText with loop */
  160. for( n=0; n<RSMAX; n++ )
  161.    {
  162.    RSItem[n].NextItem = &RSItem[n+1];
  163.    RSItem[n].LeftEdge = 0;
  164.    RSItem[n].TopEdge = 11 * n;
  165.    RSItem[n].Width = 85;
  166.    RSItem[n].Height = 11;
  167.    RSItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT;
  168.    RSItem[n].MutualExclude = (~(1 << n));
  169.    RSItem[n].ItemFill = (APTR)&RSText[n];
  170.    RSItem[n].SelectFill = NULL;
  171.    RSItem[n].Command = 0;
  172.    RSItem[n].SubItem = NULL;
  173.    RSItem[n].NextSelect = 0;
  174.  
  175.    RSText[n].FrontPen = 0;
  176.    RSText[n].BackPen = 1;
  177.    RSText[n].DrawMode = JAM2;     /* render in fore and background */
  178.    RSText[n].LeftEdge = 0;
  179.    RSText[n].TopEdge = 1;
  180.    RSText[n].ITextFont = NULL;
  181.    RSText[n].NextText = NULL;
  182.    }
  183. RSItem[RSMAX-1].NextItem = NULL;
  184. /* 300 baud item chekced */
  185. RSItem[0].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT | CHECKED;
  186.  
  187. /* initialize text for specific menu items */
  188. RSText[0].IText = (UBYTE *)"   300";
  189. RSText[1].IText = (UBYTE *)"   1200";
  190. RSText[2].IText = (UBYTE *)"   2400";
  191. RSText[3].IText = (UBYTE *)"   4800";
  192. RSText[4].IText = (UBYTE *)"   9600";
  193.  
  194. return( 0 );
  195. }
  196.  
  197.  
  198. /***************************************************/
  199. /*                Menu Definition                  */
  200. /*                                                 */
  201. /*      This section of code is where the simple   */
  202. /*   menu definition goes.                         */
  203. /***************************************************/
  204.  
  205. /* current number of available menu topics */
  206. #define MAXMENU 2
  207.  
  208. /*   declaration of menu structure array for
  209.  *   number of current topics.  Intuition
  210.  *   will use the address of this array to
  211.  *   set and clear the menus associated with
  212.  *   the window.
  213.  */
  214. struct Menu menu[MAXMENU];
  215.  
  216. /**********************************************************************/
  217. /*   The following function initializes the Menu structure array with */
  218. /*  appropriate values for our simple menu strip.  Review the manual  */
  219. /*  if you need to know what each value means.                        */
  220. /**********************************************************************/
  221. InitMenu()
  222. {
  223. menu[0].NextMenu = &menu[1];
  224. menu[0].LeftEdge = 5;
  225. menu[0].TopEdge = 0;
  226. menu[0].Width = 50;
  227. menu[0].Height = 10;
  228. menu[0].Flags = MENUENABLED;
  229. menu[0].MenuName = "File";           /* text for menu-bar display */
  230. menu[0].FirstItem = &FileItem[0];    /* pointer to first item in list */
  231.  
  232. menu[1].NextMenu = NULL;
  233. menu[1].LeftEdge = 65;
  234. menu[1].TopEdge = 0;
  235. menu[1].Width = 85;
  236. menu[1].Height = 10;
  237. menu[1].Flags = MENUENABLED;
  238. menu[1].MenuName = "BaudRate";        /* text for menu-bar display */
  239. menu[1].FirstItem = &RSItem[0];    /* pointer to first item in list */
  240.  
  241. return( 0 );
  242. }
  243.  
  244. /* declarations for the serial stuff */
  245. extern struct MsgPort *CreatePort();
  246. struct IOExtSer *Read_Request;
  247. static char rs_in[2];
  248. struct IOExtSer *Write_Request;
  249. static char rs_out[2];
  250.  
  251. /******************************************************/
  252. /*                   Main Program                     */
  253. /*                                                    */
  254. /*      This is the main body of the program.         */
  255. /******************************************************/
  256.  
  257. main()
  258. {
  259. ULONG class;
  260. USHORT code,menunum,itemnum;
  261. int KeepGoing,capture,send;
  262. char c,name[32];
  263. FILE *tranr,*trans;
  264.  
  265. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", INTUITION_REV);
  266. if( IntuitionBase == NULL )
  267.    {
  268.    puts("can't open intuition\n");
  269.    exit(TRUE);
  270.    }
  271.  
  272. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV);
  273. if( GfxBase == NULL )
  274.    {
  275.    puts("can't open graphics library\n");
  276.    exit(TRUE);
  277.    }
  278.  
  279. if(( mywindow = (struct Window *)OpenWindow(&NewWindow) ) == NULL)
  280.    {
  281.    puts("cant open window\n");
  282.    exit(TRUE);
  283.    }
  284.  
  285. Read_Request = (struct IOExtSer *)AllocMem(sizeof(*Read_Request),MEMF_PUBLIC|MEMF_CLEAR);
  286. Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  287. Read_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Read_RS",0);
  288. if(OpenDevice(SERIALNAME,NULL,Read_Request,NULL))
  289.    {
  290.    puts("Cant open Read device\n");
  291.    CloseWindow( mywindow );
  292.    DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
  293.    FreeMem(Read_Request,sizeof(*Read_Request));
  294.    exit(TRUE);
  295.    }
  296. Read_Request->IOSer.io_Command = CMD_READ;
  297. Read_Request->IOSer.io_Length = 1;
  298. Read_Request->IOSer.io_Data = (APTR) &rs_in[0];
  299.  
  300. Write_Request = (struct IOExtSer *)AllocMem(sizeof(*Write_Request),MEMF_PUBLIC|MEMF_CLEAR);
  301. Write_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  302. Write_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Write_RS",0);
  303. if(OpenDevice(SERIALNAME,NULL,Write_Request,NULL))
  304.    {
  305.    puts("Cant open Write device\n");
  306.    CloseWindow( mywindow );
  307.    DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
  308.    FreeMem(Write_Request,sizeof(*Write_Request));
  309.    DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
  310.    FreeMem(Read_Request,sizeof(*Read_Request));
  311.    exit(TRUE);
  312.    }
  313. Write_Request->IOSer.io_Command = CMD_WRITE;
  314. Write_Request->IOSer.io_Length = 1;
  315. Write_Request->IOSer.io_Data = (APTR) &rs_out[0];
  316.  
  317. Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  318. Read_Request->io_Baud = 300;
  319. Read_Request->io_ReadLen = 8;
  320. Read_Request->io_WriteLen = 8;
  321. Read_Request->io_CtlChar = 1L;
  322. Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
  323. DoIO(Read_Request);
  324. Read_Request->IOSer.io_Command = CMD_READ;
  325.  
  326. InitFileItems();
  327. InitRSItems();
  328. InitMenu();
  329. SetMenuStrip(mywindow,&menu[0]);
  330.  
  331. KeepGoing = TRUE;
  332. capture=FALSE;
  333. send=FALSE;
  334. SetAPen(mywindow->RPort,1);
  335. emit(12);
  336. emits("\n\n\nNOTE: Though the Front/Back gadgets and the Close gadget\n");
  337. emits("      can't be seen, they are still there and are active.\n");
  338. emits("      It is recommended that you use 'RUN ATERM4' to enable\n");
  339. emits("      you to go back to CLI for directories, copying files, etc.\n");
  340. emits("\n\n");
  341. BeginIO(Read_Request);
  342.  
  343. while( KeepGoing )
  344.      {
  345.      /* wait for window message or serial port message */
  346.      Wait((1 << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) | ( 1 << mywindow->UserPort->mp_SigBit));
  347.  
  348.      if (send)
  349.          {
  350.          if ((c=getc(trans)) != EOF)
  351.              {
  352.              sendchar(c);
  353.              }
  354.          else
  355.              {
  356.              fclose(trans);
  357.              emits("\nFile Sent\n");
  358.              send=FALSE;
  359.              }
  360.          }
  361.      if(CheckIO(Read_Request))
  362.         {
  363.         WaitIO(Read_Request);
  364.         c=rs_in[0] & 0x7f;
  365.         BeginIO(Read_Request);
  366.         emit(c);
  367.         if (capture)
  368.             if (c > 31 && c < 127 || c == 10)
  369.                                    /* trash them mangy ctl chars */
  370.                 putc(c , tranr);
  371.         }
  372.  
  373.      while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
  374.           {
  375.           class = NewMessage->Class;
  376.           code = NewMessage->Code;
  377.           ReplyMsg( NewMessage );
  378.           switch( class )
  379.                 {
  380.                 case CLOSEWINDOW:
  381.                    /*   User is ready to quit, so indicate
  382.                    *   that execution should terminate
  383.                    *   with next iteration of the loop.
  384.                    */
  385.                    KeepGoing = FALSE;
  386.                 break;
  387.  
  388.                 case RAWKEY:
  389.                 /*  User has touched the keyboard */
  390.                 switch( code )
  391.                       {
  392.                       case 95: /* help key */
  393.                          emits("ESC Aborts Xmodem Xfer\n");
  394.                          emits("Front/Back gadgets and Close gadget are still active though usneen.\n");
  395.                          emits("AMIGA Term 1.0\n");
  396.                          emits("Copyright 1985 by Michael Mounier\n");
  397.                       break;
  398.                       default:   
  399.                          c = toasc(code); /* get in into ascii */
  400.                          if (c != 0)
  401.                              {
  402.                              rs_out[0] = c;
  403.                              DoIO(Write_Request);
  404.                              }
  405.                       break;
  406.                       }
  407.                 break;
  408.  
  409.                 case NEWSIZE:
  410.                    emit(12);
  411.                 break;
  412.  
  413.                 case MENUPICK:
  414.                    if ( code != MENUNULL )
  415.                        {
  416.                        menunum = MENUNUM( code );
  417.                        itemnum = ITEMNUM( code );
  418.                        switch( menunum )
  419.                              {
  420.                              case 0:
  421.                                 switch( itemnum )
  422.                                       {
  423.                                       case 0:
  424.                                          if (capture == TRUE)
  425.                                              {
  426.                                              capture=FALSE;
  427.                                              fclose(tranr);
  428.                                              emits("\nEnd File Capture\n");
  429.                                              }
  430.                                          else
  431.                                              {
  432.                                              emits("\nAscii Capture:");
  433.                                              filename(name);
  434.                                              if ((tranr=fopen(name,"w")) == 0)
  435.                                                  {
  436.                                                  capture=FALSE;
  437.                                                  emits("\nError Opening File\n");
  438.                                                  break;
  439.                                                  }
  440.                                              capture=TRUE;
  441.                                              }
  442.                                       break;
  443.                                       case 1:
  444.                                          if (send == TRUE)
  445.                                              { 
  446.                                              send=FALSE;
  447.                                              fclose(trans);
  448.                                              emits("\nFile Send Cancelled\n");
  449.                                              }
  450.                                          else
  451.                                              {
  452.                                              emits("\nAscii Send:");
  453.                                              filename(name);
  454.                                              if ((trans=fopen(name,"r")) == 0)
  455.                                                  {
  456.                                                  send=FALSE;
  457.                                                  emits("\nError Opening File\n");
  458.                                                  break;
  459.                                                  }
  460.                                              send=TRUE;
  461.                                              }
  462.                                       break;
  463.                                       case 2:
  464.                                          emits("\nXmodem Receive:");
  465.                                          filename(name);
  466.                                          if (XMODEM_Read_File(name))
  467.                                             {
  468.                                             emits("\nRecieved File\n");
  469.                                             emit(8);
  470.                                             }
  471.                                          else
  472.                                             {
  473.                                             close(fd);
  474.                                             emits("Xmodem Receive Failed\n");
  475.                                             emit(8);
  476.                                             }
  477.                                       break;
  478.                                       case 3:
  479.                                          emits("\nXmodem Send:");
  480.                                          filename(name);
  481.                                          if (XMODEM_Send_File(name))
  482.                                              {
  483.                                              emits("\nSent File\n");
  484.                                              emit(8);
  485.                                              }
  486.                                          else
  487.                                              {
  488.                                              close(fd);
  489.                                              emits("\nXmodem Send Failed\n");
  490.                                              emit(8);
  491.                                              }
  492.                                       break;
  493.                                       }
  494.                              break;
  495.  
  496.                              case 1:
  497.                                 AbortIO(Read_Request);
  498.                                 switch( itemnum )
  499.                                       {
  500.                                       case 0:
  501.                                          Read_Request->io_Baud = 300;
  502.                                       break;
  503.                                       case 1:
  504.                                          Read_Request->io_Baud = 1200;
  505.                                       break;
  506.                                       case 2:
  507.                                          Read_Request->io_Baud = 2400;
  508.                                       break;
  509.                                       case 3:
  510.                                          Read_Request->io_Baud = 4800;
  511.                                       break;
  512.                                       case 4:
  513.                                          Read_Request->io_Baud = 9600;
  514.                                       break;
  515.                                       }
  516.                                 Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
  517.                                 DoIO(Read_Request);
  518.                                 Read_Request->IOSer.io_Command = CMD_READ;
  519.                                 BeginIO(Read_Request);
  520.                              break;
  521.                              } /* end of switch ( menunum ) */
  522.                        }    /*  end of if ( not null ) */
  523.                 }   /* end of switch (class) */
  524.           }   /* end of while ( newmessage )*/
  525.      }  /* end while ( keepgoing ) */
  526.  
  527. /*   It must be time to quit, so we have to clean
  528. *   up and exit.
  529. */
  530.        
  531. CloseDevice(Read_Request);
  532. DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
  533. FreeMem(Read_Request,sizeof(*Read_Request));
  534. CloseDevice(Write_Request);
  535. DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
  536. FreeMem(Write_Request,sizeof(*Write_Request));
  537. ClearMenuStrip( mywindow );
  538. CloseWindow( mywindow );
  539. exit(FALSE);
  540. } /* end of main */
  541.  
  542. /*************************************************
  543. *  function to get file name
  544. *************************************************/
  545. filename(name)
  546. char name[];
  547. {
  548. char c;
  549. ULONG class;
  550. USHORT code;
  551. int keepgoing,i;
  552. keepgoing = TRUE;
  553. i=0;
  554. while (keepgoing) {
  555.       while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
  556.            {
  557.            class = NewMessage->Class;
  558.            code = NewMessage->Code;                    name[i]=0;
  559.                     keepgoing = FALSE;
  560.                     }
  561.                  else
  562.                     {
  563.                     if (name[i] == 8)
  564.                        {
  565.                        i -=2;
  566.                        if (i < -1)
  567.                           i = -1;
  568.                        else
  569.                           {
  570.                           emit(8);
  571.                           emit(32);
  572.                           emit(8);
  573.                           }
  574.                        }
  575.                     else
  576.                        emit(c);
  577.                     }
  578.                  i += 1;
  579.                  }
  580.               }
  581.           } /* end of new message loop */
  582.       }   /* end of god knows what */
  583.       emit(13);
  584. } /* end of function */
  585.  
  586.  
  587. /*************************************************
  588. *  function to print a string
  589. *************************************************/
  590. emits(string)
  591. char string[];
  592. {
  593. int i;
  594. char c;
  595.  
  596. i=0;
  597. while (string[i] != 0)
  598.       {
  599.       c=string[i];
  600.       if (c == 10)
  601.          c = 13;
  602.       emit(c);
  603.       i += 1;
  604.       }
  605. }
  606. /**************************************************************/
  607. /* send char and read char functions for the xmodem function */
  608. /************************************************************/
  609. sendchar(ch)
  610. int ch;
  611. {
  612. rs_out[0] = ch;
  613. DoIO(Write_Request);
  614. }
  615.  
  616. readchar()
  617. {
  618. unsigned char c;
  619. int rd,ch;
  620.  
  621. rd = FALSE;
  622.  
  623. while (rd == FALSE)
  624.       {
  625.       Wait((1 << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) | ( 1 << mywindow->UserPort->mp_SigBit));
  626.       if(CheckIO(Read_Request))
  627.         {
  628.         WaitIO(Read_Request);
  629.         ch=rs_in[0];
  630.         rd = TRUE;
  631.         BeginIO(Read_Request);
  632.         }
  633.       if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort))
  634.          if ((NewMessage->Class) == RAWKEY)
  635.             if ((NewMessage->Code) == 69)
  636.                {
  637.                emits("\nUser Cancelled Transfer");
  638.                break;
  639.                }
  640.       }
  641. if (rd == FALSE)
  642.    {
  643.    timeout = TRUE;
  644.    emits("\nTimeout Waiting For Character\n");
  645.    }
  646. c = ch;
  647. return(c);
  648. }
  649.  
  650. /**************************************/
  651. /* xmodem send and recieve functions */
  652. /************************************/
  653.  
  654. XMODEM_Read_File(file)
  655.     char *file;
  656. {
  657.     int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
  658.     unsigned int checksum, j, bufptr,i;
  659.     char numb[10];
  660.     bytes_xferred = 0L;
  661.  
  662.     if ((fd = creat(file, 0)) < 0)
  663.         {
  664.         emits("Cannot Open File\n");
  665.         return FALSE;
  666.         }
  667.     else
  668.         emits("Receiving File\n");
  669.  
  670.     timeout=FALSE;
  671.     sectnum = errors = bufptr = 0;
  672.     sendchar(NAK);
  673.     firstchar = 0;
  674.     while (firstchar != EOT && errors != ERRORMAX)
  675.         {
  676.         errorflag = FALSE;
  677.  
  678.         do                                    /* get sync char */
  679.            {
  680.            firstchar = readchar();
  681.            if (timeout == TRUE)
  682.               return FALSE;
  683.            }
  684.         while (firstchar != SOH && firstchar != EOT);
  685.  
  686.         if  (firstchar == SOH)
  687.             {
  688.             emits("Getting Block ");
  689.             stci_d(numb,sectnum,i);
  690.             emits(numb);
  691.             emits("...");
  692.             sectcurr = readchar();
  693.             if (timeout == TRUE)
  694.                return FALSE;
  695.             sectcomp = readchar();
  696.             if (timeout == TRUE)
  697.                return FALSE;
  698.             if ((sectcurr + sectcomp) == 255)
  699.                 {
  700.                 if (sectcurr == (sectnum + 1 & 0xff))
  701.                     {
  702.                     checksum = 0;
  703.                     for (j = bufptr; j < (bufptr + SECSIZ); j++)
  704.                         {
  705.                         bufr[j] = readchar();
  706.                         if (timeout == TRUE)
  707.                            return FALSE;
  708.                         checksum = (checksum + bufr[j]) & 0xff;
  709.                         }
  710.                     if (checksum == readchar())
  711.                         {
  712.                         errors = 0;
  713.                         sectnum++;
  714.                         bufptr += SECSIZ;
  715.                         bytes_xferred += SECSIZ;
  716.                         emits("verified\n");
  717.                         if (bufptr == BufSize)
  718.                             {
  719.                             bufptr = 0;
  720.                             if (write(fd, bufr, BufSize) == EOF)
  721.                                 {
  722.                                 emits("\nError Writing File\n");
  723.                                 return FALSE;
  724.                                 };
  725.                             };
  726.                         sendchar(ACK);
  727.                         }
  728.                     else
  729.                         {
  730.                         errorflag = TRUE;
  731.                         if (timeout == TRUE)
  732.                            return FALSE;
  733.                         }
  734.                     }
  735.                 else
  736.                     {
  737.                     if (sectcurr == (sectnum & 0xff))
  738.                         {
  739.                         emits("\nReceived Duplicate Sector\n");
  740.                         sendchar(ACK);
  741.                         }
  742.                     else
  743.                         errorflag = TRUE;
  744.                     }
  745.                 }
  746.             else
  747.                 errorflag = TRUE;
  748.             }
  749.         if (errorflag == TRUE)
  750.             {
  751.             errors++;
  752.             emits("\nError\n");
  753.             sendchar(NAK);
  754.             }
  755.         };        /* end while */
  756.             
  757.     if ((firstchar == EOT) && (errors < ERRORMAX))
  758.         {
  759.         sendchar(ACK);
  760.         if ((bufr [bufptr-1] == 0) || (bufr [bufptr-1] == 26))
  761.         {
  762.            j = bufr[bufptr-1];                /* strip padding    */
  763.  
  764.            while (bufr [--bufptr] == j);    /* characters from    */
  765.  
  766.            bufptr++;                      /* last buffer recieved */
  767.         }
  768.         write(fd, bufr, bufptr);
  769.         close(fd);
  770.         return TRUE;
  771.         }
  772.     return FALSE;
  773. }
  774.  
  775. XMODEM_Send_File(file)
  776.     char *file;
  777. {
  778.     int sectnum, bytes_to_send, size, attempts, c, i;
  779.     unsigned checksum, j, bufptr;
  780.     char numb[10];
  781.  
  782.     timeout=FALSE;
  783.     bytes_xferred = 0;
  784.     if ((fd = open(file, 1)) < 0)
  785.         {
  786.         emits("Cannot Open Send File\n");
  787.         return FALSE;
  788.         }
  789.     else
  790.         emits("Sending File\n");
  791.     attempts = 0;
  792.     sectnum = 1;
  793. /* wait for sync char */
  794.     j=1;
  795.     while (((c = readchar()) != NAK) && (j++ < ERRORMAX));
  796.     if (j >= (ERRORMAX))
  797.         {
  798.         emits("\nReceiver not sending NAKs\n");
  799.         return FALSE;
  800.         };
  801.  
  802.     while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX)
  803.         {
  804.         if (bytes_to_send == EOF)
  805.             {
  806.             emits("\nError Reading File\n");
  807.             return FALSE;
  808.             };
  809.  
  810.         bufptr = 0;
  811.         while (bytes_to_send > 0 && attempts != RETRYMAX)
  812.             {
  813.             attempts = 0;
  814.             do
  815.                 {
  816.                 sendchar(SOH);
  817.                 sendchar(sectnum);
  818.                 sendchar(~sectnum);
  819.                 checksum = 0;
  820.                 size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
  821.                 bytes_to_send -= size;
  822.                 for (j = bufptr; j < (bufptr + SECSIZ); j++)
  823.                     if (j < (bufptr + size))
  824.                         {
  825.                         sendchar(bufr[j]);
  826.                         checksum += bufr[j];
  827.                         }
  828.                     else
  829.                         {
  830.                         sendchar(0);
  831.                         }
  832.                 sendchar(checksum & 0xff);
  833.                 attempts++;
  834.                 c = readchar();
  835.                 if (timeout == TRUE)
  836.                    return FALSE;
  837.                 }
  838.             while ((c != ACK) && (attempts != RETRYMAX));
  839.             bufptr += size;
  840.             bytes_xferred += size;
  841.             emits("Block ");
  842.             stci_d(numb,sectnum,i);
  843.             emits(numb);
  844.             emits(" sent\n");
  845.             sectnum++;
  846.             }
  847.         }
  848.     close(fd);
  849.     if (attempts == RETRYMAX)
  850.         {
  851.         emits("\nNo Acknowledgment Of Sector, Aborting\n");
  852.         return FALSE;
  853.         }
  854.     else
  855.         {
  856.         attempts = 0;
  857.         do
  858.             {
  859.             sendchar(EOT);
  860.             attempts++;
  861.             }
  862.         while ((readchar() != ACK) && (attempts != RETRYMAX) && (timeout == FALSE));
  863.          if (attempts == RETRYMAX)
  864.             emits("\nNo Acknowledgment Of End Of File\n");
  865.         };
  866.     return TRUE;
  867. }
  868.  
  869. /*************************************************
  870. *  function to output ascii chars to window
  871. *************************************************/
  872. emit(c)
  873. char c;
  874. {
  875. static short x = 0;
  876. static short y = 0;
  877. short xmax,ymax,cx,cy;
  878.  
  879. xmax = mywindow->Width;
  880. ymax = mywindow->Height;
  881.  
  882. /* cursor */
  883. if (c != 0)
  884.    {
  885.    if (x > (xmax-3))
  886.       {
  887.       cx = 7;
  888.       cy = y + 8;
  889.       }
  890.    else
  891.      {
  892.      cx = x+8;
  893.      cy = y;
  894.      }
  895.  
  896.    if (cy > (ymax-2))
  897.       {
  898.       cx = 7;
  899.       cy -= 8;
  900.       }
  901.  
  902.    SetDrMd(mywindow->RPort,COMPLEMENT);
  903.    SetAPen(mywindow->RPort,3);
  904.    RectFill(mywindow->RPort,cx-7,cy-6,cx,cy+1);
  905.    SetAPen(mywindow->RPort,1);
  906.    SetDrMd(mywindow->RPort,JAM2);
  907.  
  908.    if (x > (xmax-3))
  909.       {
  910.       x = 0;
  911.       y += 8;
  912.       }
  913.  
  914.    if (y > (ymax-2))
  915.       {
  916.       x = 0;
  917.       y -= 8;
  918.       }
  919.  
  920.    Move(mywindow->RPort,x,y);
  921.  
  922.    switch( c )
  923.          {
  924.          case '\t':
  925.             x += 40;
  926.             break;
  927.          case '\n':
  928.             break;
  929.          case 13:  /* newline */
  930.             x = 0;
  931.             y += 8;
  932.             break;
  933.          case 8:   /* backspace */
  934.             x -= 8;
  935.             if (x < 1)
  936.                x = 0;
  937.             break;
  938.          case 12:     /* page */
  939.             x = 0;
  940.             y = 6;
  941.             SetAPen(mywindow->RPort,0);
  942.             RectFill(mywindow->RPort,0,0,xmax,ymax);
  943.             SetAPen(mywindow->RPort,1);
  944.             break;
  945.          case 7:     /* bell */
  946.             ClipBlit(mywindow->RPort,0,0,mywindow->RPort,0,0,xmax,ymax,0x50);
  947.             ClipBlit(mywindow->RPort,0,0,mywindow->RPort,0,0,xmax,ymax,0x50);
  948.             break;
  949.          default:
  950.             Text(mywindow->RPort,&c,1);
  951.             x += 8;
  952.          } /* end of switch */
  953. /* cursor */
  954.    if (x > (xmax-3))
  955.       {
  956.       cx = 7;
  957.       cy = y + 8;
  958.       }
  959.    else
  960.      { 
  961.      cx = x+8;
  962.      cy = y;
  963.      }
  964.  
  965.    if (cy > (ymax-2))
  966.       {
  967.       cx = 7;
  968.       cy -= 8;
  969.       ScrollRaster(mywindow->RPort,0,8,0,0,xmax,ymax);
  970.       }
  971.  
  972.    SetAPen(mywindow->RPort,3);
  973.    RectFill(mywindow->RPort,cx-7,cy-6,cx,cy+1);
  974.    SetAPen(mywindow->RPort,1);
  975.    }
  976. }    /* end if (c !=0) */
  977.  
  978. /*************************************************
  979. *  function to take raw key data and convert it 
  980. *  into ascii chars
  981. **************************************************/
  982. toasc(code)
  983. USHORT code;
  984. {
  985. static int ctrl = FALSE;
  986. static int shift = FALSE;
  987. static int capsl = FALSE;
  988. char c;
  989. static char keys[75] = {
  990. '`' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '0' , '-' ,
  991. '=' , '\\' , 0 , '0' , 'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , 'o' ,
  992. 'p' , '[' , ']' , 0 , '1' , '2' , '3' , 'a' , 's' , 'd' , 'f' , 'g' , 'h' ,
  993. 'j' , 'k' , 'l' , ';' , '\'' , 0 , 0 , '4' , '5' , '6' , 0 , 'z' , 'x' , 'c' , 'v' ,
  994. 'b' , 'n' , 'm' , 44 , '.' , '/' , 0 , '.' , '7' , '8' , '9' , ' ' , 8 ,
  995. '\t' , 13 , 13 , 27 , 127 , 0 , 0 , 0 , '-' } ;
  996.  
  997.              switch ( code ) /* I didn't know about the Quilifier field when I write this */
  998.                     {
  999.                     case 98:
  1000.                        capsl = TRUE;
  1001.                        c = 0;
  1002.                        break;
  1003.                     case 226:
  1004.                        capsl = FALSE;
  1005.                        c = 0;
  1006.                        break;
  1007.                     case 99:
  1008.                        ctrl = TRUE;
  1009.                        c = 0;
  1010.                        break;
  1011.                     case 227:
  1012.                        ctrl = FALSE;
  1013.                        c = 0;
  1014.                        break;
  1015.                     case 96:
  1016.                     case 97:
  1017.                        shift = TRUE;
  1018.                        c = 0;
  1019.                        break;
  1020.                     case 224:
  1021.                     case 225:
  1022.                        shift = FALSE;
  1023.                        c = 0;
  1024.                        break;
  1025.                    default:
  1026.                        if (code < 75)
  1027.                           c = keys[code];
  1028.                        else
  1029.                           c = 0;
  1030.                        }
  1031.          
  1032. /* add modifiers to the keys */
  1033.  
  1034. if (c != 0)
  1035.    {
  1036.  
  1037.    if (ctrl && (c <= 'z') && (c >= 'a'))
  1038.       c -= 96;
  1039.    else if (shift)
  1040.            {
  1041.       if ((c <= 'z') && (c >= 'a'))
  1042.          c -= 32;
  1043.       else
  1044.          switch( c )
  1045.                {
  1046.           case '[':
  1047.              c = '{';
  1048.              break;
  1049.           case ']':
  1050.              c = '}';
  1051.              break;
  1052.           case '\\':
  1053.              c = '|';
  1054.              break;
  1055.           case '\'':
  1056.              c = '"';
  1057.              break;
  1058.           case ';':
  1059.              c = ':';
  1060.              break;
  1061.           case '/':
  1062.              c = '?';
  1063.              break;
  1064.           case '.':
  1065.              c = '>';
  1066.              break;
  1067.           case ',':
  1068.              c = '<';
  1069.              break;
  1070.           case '`':
  1071.              c = '~';
  1072.              break;
  1073.           case '=':
  1074.              c = '+';
  1075.              break;
  1076.           case '-':
  1077.              c = '_';
  1078.              break;
  1079.           case '1':
  1080.              c = '!';
  1081.              break;
  1082.           case '2':
  1083.              c = '@';
  1084.              break;
  1085.           case '3':
  1086.              c = '#';
  1087.              break;
  1088.           case '4':
  1089.              c = '$';
  1090.              break;
  1091.           case '5':
  1092.              c = '%';
  1093.              break;
  1094.           case '6':
  1095.              c = '^';
  1096.              break;
  1097.           case '7':
  1098.              c = '&';
  1099.              break;
  1100.           case '8':
  1101.              c = '*';
  1102.              break;
  1103.           case '9':
  1104.              c = '(';
  1105.              break;
  1106.           case '0':
  1107.              c = ')';
  1108.              break;
  1109.           default:
  1110.           } /* end switch */
  1111.       } /* end shift */
  1112.    else if (capsl && (c <= 'z') && (c >= 'a'))
  1113.            c -= 32;
  1114.    } /* end modifiers */
  1115.    return(c);
  1116. } /* end of routine */
  1117. /* end of file */
  1118.  
  1119.